home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 701-725 / 708 / intuisup / intuisup42.lha / Intuisup / source.lha / Files / files.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  11KB  |  453 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1991 by Torsten Jürgeleit
  4.  *
  5.  *    Name .....: files.c
  6.  *    Created ..: Thursday 19-Dec-91 20:00:48
  7.  *    Revision .: 0
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    11-Apr-92   Torsten Jürgeleit      corrected abort if line too long
  12.  *    19-Dec-91   Torsten Jürgeleit      Created this file!
  13.  *
  14.  ****************************************************************************
  15.  *
  16.  *    Support routines for reading and parsing text files
  17.  *
  18.  * $Revision Header ********************************************************/
  19.  
  20.     /* Includes */
  21.  
  22. #include <exec/types.h>
  23. #include <exec/memory.h>
  24. #include <libraries/dos.h>
  25. #include <libraries/diskfont.h>
  26. #include <intuition/intuition.h>
  27. #ifdef AZTEC_C
  28. #include <functions.h>   /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
  29. #endif
  30. #include <libraries/memwatch.h>   /* header file for memory debug link library (Fish 240) - AFTER functions.h */
  31. #include <string.h>
  32. #include "/render/render.h"
  33. #include "files.h"
  34.  
  35.     /* Defines for internal flags */
  36.  
  37. #define TEXT_FILE_FLAG_READ_NEXT_LINE        (1 << 15)    /* if current line is empty or continued then read next line too */
  38.  
  39.     /* Static prototypes */
  40.  
  41. SHORT fill_read_buffer(struct FileData  *fd);
  42. BPTR  dos_open(BYTE *name, LONG flags);
  43. LONG  dos_read(BPTR fh, BYTE *buffer, LONG size);
  44. VOID  dos_close(BPTR fh);
  45.  
  46.     /* Static pragmas */
  47.  
  48. #pragma regcall(fill_read_buffer(a0))
  49. #pragma regcall(dos_open(a0,d0))
  50. #pragma regcall(dos_read(a0,a1,d0))
  51. #pragma regcall(dos_close(a0))
  52.  
  53.     /* Open text file */
  54.  
  55.    struct FileData *
  56. open_text_file(BYTE *name, USHORT read_buffer_size, USHORT line_buffer_size,
  57.                                    USHORT flags)
  58. {
  59.    struct FileData  *fd = NULL;
  60.  
  61.    if (name && read_buffer_size && line_buffer_size) {
  62.       BPTR fh;
  63.  
  64.       if (fh = dos_open(name, (LONG)MODE_OLDFILE)) {
  65.      if (!(fd = AllocMem((LONG)(sizeof(struct FileData) +
  66.                    read_buffer_size + line_buffer_size + 1),
  67.                               (LONG)MEMF_PUBLIC))) {
  68.         dos_close(fh);
  69.      } else {
  70.  
  71.         /* Init internal file data */
  72.         fd->fd_Name           = name;
  73.         fd->fd_ReadBufferSize = read_buffer_size;
  74.         fd->fd_LineBufferSize = line_buffer_size;
  75.         fd->fd_Flags          = flags;
  76.         fd->fd_FileHandle     = fh;
  77.         fd->fd_ReadBuffer     = (BYTE *)(fd + 1);
  78.         fd->fd_CurrentPtr     = NULL;
  79.         fd->fd_LineBuffer     = fd->fd_ReadBuffer + read_buffer_size;
  80.         fd->fd_ID             = ISUP_ID;
  81.  
  82.         /* Init public file data struct */
  83.         fd->fd_Line    = NULL;
  84.         fd->fd_LineLen = 0;
  85.         fd->fd_LineNum = 0;
  86.      }
  87.       }
  88.    }
  89.    return(fd);
  90. }
  91.     /* Read line from text file */
  92.  
  93.    SHORT
  94. read_text_line(struct FileData  *fd)
  95. {
  96.    SHORT status = TEXT_FILE_STATUS_NORMAL;
  97.  
  98.    if (!fd || fd->fd_ID != ISUP_ID) {
  99.       status = TEXT_FILE_ERROR_NO_FILE_DATA;
  100.    } else {
  101.       BYTE   *line = fd->fd_LineBuffer;
  102.       USHORT flags = fd->fd_Flags, len = 0;
  103.  
  104.       do {
  105.      BYTE c, *ptr;
  106.  
  107.      /* Fill read buffer */
  108.      if (!(ptr = fd->fd_CurrentPtr) || ptr >= fd->fd_EndPtr) {
  109.         if ((status = fill_read_buffer(fd)) == TEXT_FILE_STATUS_NORMAL) {
  110.            ptr = fd->fd_CurrentPtr;
  111.         }
  112.      }
  113.      if (status == TEXT_FILE_STATUS_NORMAL) {
  114.  
  115.         /* Strip leading white space */
  116.         if (flags & TEXT_FILE_FLAG_TRIM_LINE) {
  117.            while ((c = *ptr) == ' ' || c == '\t') {
  118.           if (++ptr >= fd->fd_EndPtr) {
  119.              if ((status = fill_read_buffer(fd)) !=
  120.                           TEXT_FILE_STATUS_NORMAL) {
  121.             break;
  122.              } else {
  123.             ptr = fd->fd_CurrentPtr;
  124.              }
  125.           }
  126.            }
  127.         }
  128.         if (status == TEXT_FILE_STATUS_NORMAL) {
  129.  
  130.            /* Copy line from read buffer to line buffer */
  131.            if (flags & TEXT_FILE_FLAG_SKIP_COMMENTS) {
  132.           BOOL comment = FALSE;
  133.  
  134.           /* Copy without comments */
  135.           while ((c = *ptr) != '\n' || comment == TRUE) {
  136.  
  137.              /* Write char to line buffer */
  138.              if (comment == FALSE) {
  139.             if (len >= fd->fd_LineBufferSize) {
  140.                status = TEXT_FILE_ERROR_LINE_TOO_LONG;
  141.                break;
  142.             } else {
  143.                *line++ = c;
  144.                len++;
  145.             }
  146.              }
  147.  
  148.              /* Increment ptr and fill read buffer if neccessary */
  149.              if (++ptr == fd->fd_EndPtr) {
  150.             if ((status = fill_read_buffer(fd)) !=
  151.                           TEXT_FILE_STATUS_NORMAL) {
  152.                break;
  153.             } else {
  154.                ptr = fd->fd_CurrentPtr;
  155.             }
  156.              }
  157.  
  158.              /* Check for comment delimiters */
  159.              if (comment == FALSE) {
  160.             if (c == '/' && *ptr == '*') {
  161.                comment = TRUE;
  162.  
  163.                /* Remove '/' from line */
  164.                line--;
  165.                len--;
  166.             }
  167.              } else {
  168.             if (c == '\n') {
  169.                fd->fd_LineNum++;
  170.             } else {
  171.                if (c == '*' && *ptr == '/') {
  172.                   comment = FALSE;
  173.  
  174.                   /* Skip '/' */
  175.                   if (++ptr == fd->fd_EndPtr) {
  176.                  if ((status = fill_read_buffer(fd)) !=
  177.                           TEXT_FILE_STATUS_NORMAL) {
  178.                     break;
  179.                  } else {
  180.                     ptr = fd->fd_CurrentPtr;
  181.                  }
  182.                   }
  183.                }
  184.             }
  185.              }
  186.           }
  187.            } else {
  188.  
  189.           /* Copy with comments */
  190.           while ((c = *ptr) != '\n') {
  191.  
  192.              /* Write char to line buffer */
  193.              if (len >= fd->fd_LineBufferSize) {
  194.             status = TEXT_FILE_ERROR_LINE_TOO_LONG;
  195.             break;
  196.              } else {
  197.             *line++ = c;
  198.             len++;
  199.  
  200.             /* Increment ptr and fill read buffer if neccessary */
  201.             if (++ptr == fd->fd_EndPtr) {
  202.                if ((status = fill_read_buffer(fd)) !=
  203.                           TEXT_FILE_STATUS_NORMAL) {
  204.                   break;
  205.                } else {
  206.                   ptr = fd->fd_CurrentPtr;
  207.                }
  208.             }
  209.              }
  210.           }
  211.            }
  212.            if (status == TEXT_FILE_STATUS_NORMAL) {
  213.  
  214.           /* Strip trailing white space */
  215.           if (flags & TEXT_FILE_FLAG_TRIM_LINE) {
  216.              while (len && ((c = *(line - 1)) == ' ' || c == '\t')) {
  217.             line--;
  218.             len--;
  219.              }
  220.           }
  221.           if (!len) {
  222.  
  223.              /* Check for skip empty line */
  224.              if (flags & TEXT_FILE_FLAG_SKIP_EMPTY_LINES) {
  225.             flags |= TEXT_FILE_FLAG_READ_NEXT_LINE;
  226.              } else {
  227.             flags &= ~TEXT_FILE_FLAG_READ_NEXT_LINE;
  228.              }
  229.           } else {
  230.  
  231.              /* Check for line continuation - last char is '\'? */
  232.              if (flags & TEXT_FILE_FLAG_LINE_CONTINUATION) {
  233.             if (*(line - 1) == '\\') {
  234.                flags |= TEXT_FILE_FLAG_READ_NEXT_LINE;
  235.  
  236.                /* Strip '\' from end of line */
  237.                line--;
  238.                len--;
  239.             } else {
  240.                flags &= ~TEXT_FILE_FLAG_READ_NEXT_LINE;
  241.             }
  242.              } else {
  243.             flags &= ~TEXT_FILE_FLAG_READ_NEXT_LINE;
  244.              }
  245.           }
  246.  
  247.           /* Mark end of string */
  248.           *line             = '\0';
  249.           fd->fd_CurrentPtr = ptr + 1;   /* skip trailing '\n' */
  250.           fd->fd_LineNum++;
  251.            }
  252.         }
  253.      }
  254.       } while (status == TEXT_FILE_STATUS_NORMAL &&
  255.                    (flags & TEXT_FILE_FLAG_READ_NEXT_LINE));
  256.       /* Init public data */
  257.       if (status == TEXT_FILE_STATUS_NORMAL) {
  258.      fd->fd_Line    = fd->fd_LineBuffer;
  259.      fd->fd_LineLen = len;
  260.       } else {
  261.      fd->fd_Line    = NULL;
  262.      fd->fd_LineLen = 0;
  263.       }
  264.    }
  265.    return(status);
  266. }
  267.     /* Fill read buffer from text file */
  268.  
  269.    STATIC SHORT
  270. fill_read_buffer(struct FileData  *fd)
  271. {
  272.    LONG  len;
  273.    SHORT status;
  274.  
  275.    if ((len = dos_read(fd->fd_FileHandle, fd->fd_ReadBuffer, (LONG)
  276.                        fd->fd_ReadBufferSize)) == -1L) {
  277.       status = TEXT_FILE_ERROR_READ_FAILED;
  278.    } else {
  279.       if (!len) {
  280.      status = TEXT_FILE_STATUS_EOF;
  281.       } else {
  282.      fd->fd_CurrentPtr = fd->fd_ReadBuffer;
  283.      fd->fd_EndPtr     = fd->fd_ReadBuffer + len;
  284.      status            = TEXT_FILE_STATUS_NORMAL;
  285.       }
  286.    }
  287.    return(status);
  288. }
  289.     /* Close text file */
  290.  
  291.    VOID
  292. close_text_file(struct FileData  *fd)
  293. {
  294.    if (fd && fd->fd_ID == ISUP_ID) {
  295.       dos_close(fd->fd_FileHandle);
  296.       FreeMem(fd, (LONG)(sizeof(struct FileData) + fd->fd_ReadBufferSize +
  297.                         fd->fd_LineBufferSize + 1));
  298.    }
  299. }
  300.     /* DOS calls between open and close of dos library
  301.      * -> neccessary for DOS calls from within intuisup.library
  302.      */
  303. #asm
  304. ;---------------------------------------------------------------------------
  305. ; Support macros
  306. ;---------------------------------------------------------------------------
  307.  
  308. PUSH    MACRO
  309.     movem.l    \1,-(sp)
  310.     ENDM
  311.  
  312. PULL    MACRO
  313.     movem.l    (sp)+,\1
  314.     ENDM
  315.  
  316. CALLSYS    MACRO
  317.     XREF    _LVO\1
  318.     jsr    _LVO\1(a6)
  319.     ENDM
  320.  
  321. ;---------------------------------------------------------------------------
  322. ; External definitions
  323. ;---------------------------------------------------------------------------
  324.  
  325.     XDEF    _dos_open
  326.     XDEF    _dos_read
  327.     XDEF    _dos_close
  328.  
  329. ;---------------------------------------------------------------------------
  330. ; BPTR dos_open(BYTE *name, LONG flags)
  331. ;                    a0         d0
  332. ;---------------------------------------------------------------------------
  333.  
  334. _dos_open:
  335.     PUSH    d2-d3/a2/a6
  336.  
  337.     ; --- save parameters
  338.     move.l    a0,a2            ; a2 := file name ptr
  339.     move.l    d0,d2            ; d2 := flags
  340.     moveq    #0,d3            ; d3 := return code
  341.  
  342.     ; --- open dos library
  343.     move.l    (4).w,a6        ; a6 := SysBase
  344.     lea    dos_name(pc),a1        ; a1 := library name
  345.     moveq    #0,d0            ; d0 := version
  346.     CALLSYS    OpenLibrary
  347.     tst.l    d0
  348.     beq.s    do_exit
  349.  
  350.     ; --- call DOS function Open()
  351.     move.l    d0,a6            ; a6 := DosBase
  352.     move.l    a2,d1            ; d1 := file name ptr
  353.                     ; d2 := flags
  354.     jsr    -$1e(a6)        ; CALLSYS Open -> Bug in c16.lib (POSITIVE lib offset)
  355.     move.l    d0,d3            ; d3 := BPTR to file handle
  356.  
  357.     ; --- close dos library
  358.     move.l    a6,a1            ; a1 := DosBase
  359.     move.l    (4).w,a6        ; a6 := SysBase
  360.     CALLSYS    CloseLibrary
  361.  
  362. do_exit:
  363.     ; --- prepare return code
  364.     move.l    d3,d0
  365.  
  366.     PULL    d2-d3/a2/a6
  367.     rts
  368.  
  369. ;---------------------------------------------------------------------------
  370. ; LONG dos_read(BPTR fh, BYTE *buffer, LONG size);
  371. ;                  a0         a1          d0
  372. ;---------------------------------------------------------------------------
  373.  
  374. _dos_read:
  375.     PUSH    d2-d4/a2-a3/a6
  376.  
  377.     ; --- save parameters
  378.     move.l    a0,a2            ; a2 := BPTR to file handle
  379.     move.l    a1,a3            ; a3 := buffer ptr
  380.     move.l    d0,d3            ; d3 := size
  381.     moveq    #-1,d4            ; d4 := return code
  382.  
  383.     ; --- open dos library
  384.     move.l    (4).w,a6        ; a6 := SysBase
  385.     lea    dos_name(pc),a1        ; a1 := library name
  386.     moveq    #0,d0            ; d0 := version
  387.     CALLSYS    OpenLibrary
  388.     tst.l    d0
  389.     beq.s    dr_exit
  390.  
  391.     ; --- call DOS function Read()
  392.     move.l    d0,a6            ; a6 := DosBase
  393.     move.l    a2,d1            ; d1 := BPTR to file handle
  394.     move.l    a3,d2            ; d2 := buffer ptr
  395.                     ; d3 := size
  396.     jsr    -$2a(a6)        ; CALLSYS Read -> Bug in c16.lib (POSITIVE lib offset)
  397.     move.l    d0,d4            ; d4 := num of characters read
  398.  
  399.     ; --- close dos library
  400.     move.l    a6,a1            ; a1 := DosBase
  401.     move.l    (4).w,a6        ; a6 := SysBase
  402.     CALLSYS    CloseLibrary
  403.  
  404. dr_exit:
  405.     ; --- prepare return code
  406.     move.l    d4,d0
  407.  
  408.     PULL    d2-d4/a2-a3/a6
  409.     rts
  410.  
  411. ;---------------------------------------------------------------------------
  412. ; VOID dos_close(BPTR fh);
  413. ;                   a0
  414. ;---------------------------------------------------------------------------
  415.  
  416. _dos_close:
  417.     PUSH    a2/a6
  418.  
  419.     ; --- save parameters
  420.     move.l    a0,a2            ; a2 := BPTR to file handle
  421.  
  422.     ; --- open dos library
  423.     move.l    (4).w,a6        ; a6 := SysBase
  424.     lea    dos_name(pc),a1        ; a1 := library name
  425.     moveq    #0,d0            ; d0 := version
  426.     CALLSYS    OpenLibrary
  427.     tst.l    d0
  428.     beq.s    dc_exit
  429.  
  430.     ; --- call DOS function Close()
  431.     move.l    d0,a6            ; a6 := DosBase
  432.     move.l    a2,d1            ; d1 := BPTR to file handle
  433.     jsr    -$24(a6)        ; CALLSYS Close -> Bug in c16.lib (POSITIVE lib offset)
  434.  
  435.     ; --- close dos library
  436.     move.l    a6,a1            ; a1 := DosBase
  437.     move.l    (4).w,a6        ; a6 := SysBase
  438.     CALLSYS    CloseLibrary
  439.  
  440. dc_exit:
  441.     PULL    a2/a6
  442.     rts
  443.  
  444. ;---------------------------------------------------------------------------
  445. ; Static data
  446. ;---------------------------------------------------------------------------
  447.  
  448. dos_name:
  449.     dc.b    "dos.library"
  450.  
  451.     EVEN
  452. #endasm
  453.